home *** CD-ROM | disk | FTP | other *** search
- /*
- brs_calltree: Browsing an Analysis Tool for C-source code;
- Print calltree structure of a project
-
- Copyright (C) 1993 Eckehard Stolz
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation (version 2 of the License).
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-
-
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <time.h>
-
- #include "hash.h"
- #include "c-bat.h"
- #include "clients.h"
-
-
- /* Types for Hash-Entrys
- */
- #define TYPE_FUNCTION 0x1
- #define TYPE_FILE 0x2
-
- #define MAX_LINE 256 /* maximum of line lenght */
-
- /* Flags used in Hash-Table-Entry
- */
- #define FLAG_PRINTED 0x1 /* Print Identifier */
- #define FLAG_IGNORE 0x2 /* Ignore Identifier */
- #define FLAG_IN_HASH 0x4 /* Allready inserted in Hash-Index-Array */
- #define FLAG_OWN_TREE 0x8 /* use own tree for that function */
- #define FLAG_PROCESSED 0x10 /* Function is allready processed */
- #define FLAG_TERMINATE 0x20 /* Do not process deeper */
- #define FLAG_CALLED 0x40 /* Used to not process recursive function */
- #define FLAG_TREE_CALLED 0x80 /* Used to not process recursive function */
- #define FLAG_TREE_TOP 0x100 /* this function is top-node of a tree */
-
- #define max(x,y) (((x) > (y)) ? (x) : (y))
-
-
- /* Additional data, stored in Hash-Table. Here used to store position
- of any function defined in the source-project for the output
- "defined in ... at line ..."
-
- */
-
- struct pos_e
- { long file; /* index of the file in the hash-table */
- long line; /* linenumer, where function has been called */
- short len; /* length of the string "file,line" */
- struct pos_e *next; /* next position */
- };
-
- struct son_e
- { long son;
- struct pos_e *pos;
- };
-
- struct hash_add_data
- { long level; /* actual level of call stack (maximum value) */
- long max_chars; /* maximum of characters used to print line */
- long cnt_sons; /* cnt of sons of this node */
- long total_cnt_n; /* total cnt of nodes in this leave */
- long called; /* how many times has function been called */
- long file; /* file, where function is defined */
- long line; /* line, where function is defined */
- struct son_e *sons; /* array of sons */
- long father; /* father of this node */
- struct pos_e pos; /* position (file/line) where this call is */
- };
-
- typedef struct hash_add_data t_hash_add;
-
-
- /* these strings control the output of the tree.
- */
- #define MAX_INDENT 20
- #define FILE_LINE_FORMAT "%s %d" /* for output of file and line */
-
- /* 123456789 */
- char blank_pre[MAX_INDENT+1];
- char noblank_pre[MAX_INDENT+1];
- char last_string[MAX_INDENT+1];
- char mid_string[MAX_INDENT+1];
- char filler_string[MAX_INDENT+1];
- char file_line_format[80] = FILE_LINE_FORMAT;
-
- char c_hline = '-';
- char c_vline = '|';
- char c_tline = '+';
- char c_corner = '`';
- char c_blank = ' ';
- char c_begin = ' ';
- char c_filler = '.';
-
- short indent_size = 4;
-
- #define LEVEL_OFFSET (strlen(blank_pre)) /* offset for each new level */
-
- #define calculate_max_chars(s,l,t) (strlen(s) + (l) * LEVEL_OFFSET + (t))
-
- static char funct_filename[MAX_FILENAME]; /* File, where function */
-
- static char module_file[MAX_FILENAME]; /* file with module-file-assign*/
- static char exclude_file[MAX_FILENAME]; /* list of exclude symbols */
- static char terminate_file[MAX_FILENAME]; /* list of exclude symbols */
-
- static char act_function[MAX_IDENT]; /* act. Function Ident */
-
- static char target_function[2*STRINGSIZE]; /* Ident of searched function */
- static char target_variable[MAX_IDENT]; /* Ident of searched variable */
-
- static char output_line[MAX_LINE]; /* used for creating output */
-
- static long f_line; /* Source-Line, where function called/defined */
- static long f_line2; /* Source-Line, where called function defined */
-
- static long total_max_chars = 0; /* maximum string for left side of a print-line */
- static long total_max_level = 0; /* maximum level in deeperst leave of calltree */
-
- static long line_length = 80; /* default for the lenght of a line (may be increased */
- /* if necessary ) */
-
- /* FLAGS
- */
-
-
- /* set to 1 if we have to print a full tree: may be BIG !
- */
- static short flag_full_tree = 0;
-
- /* set to 1 if we have to print function pointers
- */
- static short flag_funct_pointer = 0;
-
- /* set treshhold for starting a new tree for a function depending on the
- numbers of calls to this function
-
- 0 ... no own tree for this kind of functions
- */
- static short trshold_called = 0;
-
- /* set treshhold for starting a new tree for a function if the
- called-treshhold has been reached, depending on the
- number of nodes of this sub_tree
-
- 0 ... cont of sons not important
- */
- static short trshold_sons = 0;
-
- /* set to 1 if we should NOT print information to stderr while processing
- functions, symbol-files, ...
- */
- static short quiet_flag = 0;
-
- /* set to 1 if we should ignore library symbols !
- library symbols are symbols not defined in the project
- */
- static short ignore_lib_symbols = 0;
- static short mark_lib_symbols = 0;
-
- /* Flag, if (and what) position should be printed
-
- 0 ... do not print position
- 1 ... print position where function called (default)
- 2 ... print position where function defined
- */
- static short flag_print_position = 1;
-
-
- /* All symbols, which have to be printed, are stored in the hashtable
- and aditionally stored in this array (by their hash-indizes).
- So we don't have to check the whole hash-table for nonnull-entries
- */
- static long *hash_array = NULL;
- static long hash_array_cnt = 0;
- static long hash_array_size = 0;
-
- /* used for locally collecting sons of a function-node
- */
- static struct son_e *son_hash_array = NULL;
- static long son_hash_array_cnt = 0;
- static long son_hash_array_size = 0;
-
-
- /* prototypes
- */
- extern void reset_hashtable(void);
- extern long Add_ident_to_hash(char *ident, short flag, void *add_data, short type );
- extern long get_total_nodes(long index, long level, struct pos_e *p);
- extern void print_all_nodes(long index, long level, struct pos_e *p, char last);
- extern void print_line( long level, char *ident, t_hash_add *add, struct pos_e *p, char *suffix, char last_flag);
-
-
- /* This function add's a symbol to the symbol-table. If the flag for
- printing is set, the index is added to the hash-index-array which
- causes the symbol to be printed after processing
-
- return-value is the index in the hash-table
- */
- long Add_ident_to_hash(char *ident, short flag, void *add_data, short type )
- { long index ;
- t_hash_data h_entry;
-
- if( ident[0] == 0 )
- return; /* nothing to do with an empty item */
-
- strncpy( h_entry.ident, ident, SZE_HASH_IDENT - 1 );
- h_entry.ident[SZE_HASH_IDENT - 1] = 0;
- h_entry.type = type;
- h_entry.flags = flag;
- h_entry.data = add_data;
- index = insert_token( &h_entry );
-
- return( index );
- }
-
-
- /* add index to hash array index to easyly find function-hash-indezes
- again
- */
- void Add_to_Hash_Index_Array(long index)
- {
-
- hash_array[hash_array_cnt] = index;
- hash_array_cnt++;
-
- if( hash_array_cnt == hash_array_size)
- { hash_array_size += HASH_ARRAY_INIT_SIZE;
- hash_array = realloc( hash_array,
- sizeof( long ) * hash_array_size );
-
- if( !hash_array )
- { fprintf(stderr, "Error ! Cannot allocate %ld Bytes of Memory\n",
- sizeof( long ) * hash_array_size );
- exit(1);
- }
- }
- }
-
- /* add index to hash array index to easyly find function-hash-indezes
- again
- */
- void Add_to_Son_Array(struct son_e son)
- {
-
- son_hash_array[son_hash_array_cnt] = son;
- son_hash_array_cnt++;
-
- if( son_hash_array_cnt == son_hash_array_size)
- { son_hash_array_size += HASH_ARRAY_INIT_SIZE;
- son_hash_array = realloc( son_hash_array,
- sizeof( struct son_e ) * son_hash_array_size );
-
- if( !son_hash_array )
- { fprintf(stderr, "Error ! Cannot allocate %ld Bytes of Memory\n",
- sizeof( struct son_e ) * son_hash_array_size );
- exit(1);
- }
- }
- }
-
-
- /* opens a file with symbols and adds them to the symbol-table
- */
- void read_symbols(char *file, short flag)
- { long index;
- t_hash_data data;
- t_hash_add *p_h_add_s;
- FILE *fp;
-
-
- fp = fopen( file, "r" );
- if( !fp )
- { fprintf(stderr, "Cannot open File %s !\nAborting !", file );
- exit(1);
- }
-
- while( !feof(fp) )
- { if( fgets( act_function, MAX_IDENT, fp ) )
- { if( act_function[strlen(act_function)-1] == '\n' )
- act_function[strlen(act_function)-1] = 0;
-
- p_h_add_s = malloc( sizeof( t_hash_add ) );
-
- if( !p_h_add_s )
- { fprintf(stderr, "Not enough physical memory available !\n");
- exit(1);
- }
- /* new entry: insert initial values
- */
- p_h_add_s->level = -1;
- p_h_add_s->called = 1;
- p_h_add_s->cnt_sons = 0;
- p_h_add_s->total_cnt_n = 0;
- p_h_add_s->father = TOKEN_NOT_FOUND;
-
- p_h_add_s->pos.file = TOKEN_NOT_FOUND;
- p_h_add_s->pos.line = 0;
- p_h_add_s->pos.next = NULL;
-
- Add_ident_to_hash( act_function, flag, p_h_add_s, 0 );
-
- if( !quiet_flag )
- fprintf(stderr, "Symbol: \"%s\" \n", act_function);
-
- }
- }
-
- fclose(fp);
- }
-
- /* build all strings from the tree-characters.
-
- used to rebuild the strings if they had been changed
- */
- void create_output_strings(void)
- { short i;
-
- blank_pre[indent_size] = 0;
- noblank_pre[indent_size] = 0;
- last_string[indent_size] = 0;
- mid_string[indent_size] = 0;
- filler_string[1] = 0;
-
- for( i = 0; i < indent_size; i++)
- { blank_pre[i] = c_blank;
- noblank_pre[i] = c_blank;
- }
- noblank_pre[0] = c_vline;
-
- for( i = 1; i < indent_size - 1; i++ )
- { last_string[i] = c_hline;
- mid_string[i] = c_hline;
- }
- mid_string[0] = c_tline;
- mid_string[indent_size-1] = c_begin;
- last_string[0] = c_corner;
- last_string[indent_size-1] = c_begin;
-
- filler_string[0] = c_filler;
- }
-
-
-
- main( int argc, char *argv[] )
- { short flag;
- short ret,
- ret2,
- code,
- ignore_this_symbol,
- static_flag;
-
- int server;
-
- FILE *fp;
-
- char funct_in[STRINGSIZE];
- char funct[STRINGSIZE];
- char file[2*STRINGSIZE];
- char file2[2*STRINGSIZE];
- char module[2*STRINGSIZE];
-
- struct son_e created_son;
-
- t_hash_add *p_h_add,
- *p_h_add_s;
-
- t_hash_data h_data,
- h_data_f,
- h_data_s;
-
- long i,
- j,
- index,
- line,
- line_end,
- line2,
- index_s;
-
-
- if( argc <= 1 || argv[1][1] == '?' )
- { fprintf(stderr, "Usage: brs_calltree [Options] <funct> [<file>]\n" );
- fprintf(stderr, "Print a calltree from function <funct>, defined in <file>\n");
- fprintf(stderr, "This program needs the browser-server run in background !\n");
- fprintf(stderr, "\nOptions:\n");
- fprintf(stderr, "-b <browser-file> Connect to server processing this browser file\n");
- fprintf(stderr, "-x <exclude-file> Exclude symbols given in exclude-file\n");
- fprintf(stderr, " format of exclude-file : one symbol per line\n");
- fprintf(stderr, "-s <stop-file> Stop downwalking at symbols given in stop-file\n");
- fprintf(stderr, " format of stop-file : one symbol per line\n");
- fprintf(stderr, "-n <tree-file> Own tree for every symbol given in tree-file\n");
- fprintf(stderr, " format of tree-file : one symbol per line\n");
- fprintf(stderr, "-q Quiet: Do not print information to stderr\n");
- fprintf(stderr, "-f Include Function-Pointers used outside functions\n");
- fprintf(stderr, "\n");
- fprintf(stderr, "-pc Print position where functions called (default)\n");
- fprintf(stderr, "-pd Print position where functions defined\n");
- fprintf(stderr, "-p- Do not print position at all\n");
- fprintf(stderr, "-lm Mark library-symbols with \"(L)\"\n");
- fprintf(stderr, "-l- Do not print library symbols\n");
- fprintf(stderr, "\nOptions controlling look of the output-tree defaults\n");
- fprintf(stderr, "-i<value> Numbers of chars for indent (>= 2) 4\n");
- fprintf(stderr, "-F<filename> File containing formatstring for position \"%%s %%d\"\n");
- fprintf(stderr, "-d<char> Character for filling line '.'\n");
- fprintf(stderr, "-ch<char> Character for horizontal line '-'\n");
- fprintf(stderr, "-cv<char> Character for vertical line '|'\n");
- fprintf(stderr, "-ct<char> Character for T-line '+'\n");
- fprintf(stderr, "-cc<char> Character for corner '`'\n");
- fprintf(stderr, "-cb<char> Character before function name ' '\n");
- exit(1);
- }
-
- target_function[0] = 0;
- funct_filename[0] = 0;
-
- /* we have to preprocess args for looking for the
- -q flag. We need to initialize the hash-table before
- fully parsing arguments
- */
- for( i = 1; i < argc; i++ )
- { if( argv[i][0] == '-' )
- { switch( argv[i][1] )
- { case 'q' : /* quiet-flag: no Info to stderr */
- quiet_flag = 1;
- break;
-
- default:
- break;
- }
- }
- }
-
- if( !quiet_flag )
- fprintf( stderr, "Initializing Hashtable ...\n");
-
- init_hashtable ();
-
- for( i = 1; i < argc; i++ )
- { if( argv[i][0] != '-' )
- { /* function or filename */
- if( target_function[0] )
- { if( funct_filename[0] )
- { fprintf(stderr, "Unknown Option \"%s\" !\n", argv[i] );
- fprintf(stderr, "Type \"brs_calltree -?\" for help !\n" );
- exit(1);
- }
- else
- strcpy( funct_filename, argv[i] );
- }
- else
- strcpy( target_function, argv[i] );
- }
- else
- /* ordinary option given: */
- { switch( argv[i][1] )
- { case 'x' : /* Exclude-Filename */
- if( !quiet_flag )
- fprintf( stderr, "Reading symbols from exclude-file ...\n");
- if( argv[i][2] )
- { /* Filename given without blank */
- read_symbols( argv[i] + 2, FLAG_IGNORE );
- }
- else
- { /* Browser-filename is in the next argument
- */
- i++;
- read_symbols( argv[i], FLAG_IGNORE );
- }
- break;
-
- case 'b' : /* Browser-Filename */
- if( argv[i][2] )
- { /* Filename given without blank */
- server = brs_get_server_id( argv[i] + 2 );
- }
- else
- { /* Browser-filename is in the next argument
- */
- i++;
- server = brs_get_server_id( argv[i] );
- }
- if( server < 0 )
- { fprintf(stderr, "Server with browser file \"%s\" not found !\n",
- argv[i] );
- exit(1);
- }
- if( (ret = brs_connect_server( server )) > 0 )
- { fprintf(stderr, "Server connection failed (Error: %hd) !\n",
- ret );
- exit(1);
- }
- break;
-
- case 's' : /* Stop-Filename */
- if( !quiet_flag )
- fprintf( stderr, "Reading symbols from stop-file ...\n");
-
- if( argv[i][2] )
- { /* Filename given without blank */
- read_symbols( argv[i] + 2, FLAG_TERMINATE );
- }
- else
- { /* Browser-filename is in the next argument
- */
- i++;
- read_symbols( argv[i], FLAG_TERMINATE );
- }
- break;
-
- case 'n' : /* Tree-Filename */
- if( !quiet_flag )
- fprintf( stderr, "Reading symbols from tree-file ...\n");
-
- if( argv[i][2] )
- { /* Filename given without blank */
- read_symbols( argv[i] + 2, FLAG_OWN_TREE );
- }
- else
- { /* Browser-filename is in the next argument
- */
- i++;
- read_symbols( argv[i], FLAG_OWN_TREE );
- }
- break;
-
- case 'p' : /* Print-position */
- switch( argv[i][2] )
- { case 'c': /* where function called */
- flag_print_position = 1;
- break;
- case 'd': /* where function defined */
- flag_print_position = 2;
- break;
- case '-': /* no position at all */
- flag_print_position = 0;
- break;
- default:
- fprintf(stderr, "Unknown Option \"%s\" !\n", argv[i] );
- fprintf(stderr, "Type \"brs_calltree -?\" for help !\n" );
- exit(1);
- }
- break;
-
- case 'F' : /* format string for position output */
- if( argv[i][2] )
- { /* Filename given without blank */
- fp = fopen( argv[i] + 2, "r" );
- if( !fp )
- { fprintf(stderr, "Cannot open formatstring-file: \"%s\" !\n", argv[i] + 2 );
- fprintf(stderr, "Using default !\n");
- break;
- }
- }
- else
- { /* Browser-filename is in the next argument
- */
- i++;
- fp = fopen( argv[i], "r" );
- if( !fp )
- { fprintf(stderr, "Cannot open formatstring-file: \"%s\" !\n", argv[i] );
- fprintf(stderr, "Using default !\n");
- break;
- }
- }
-
- for( j = 0; j < 80; j++)
- { file_line_format[j] = fgetc(fp);
-
- if( file_line_format[j] == EOF ||
- !isprint(file_line_format[j]) )
- break;
- }
- fclose(fp);
-
- file_line_format[j] = 0;
- break;
-
- case 'i' : /* number of chars indenting */
- indent_size = atoi( argv[i] + 2);
- if( indent_size < 2 || indent_size > 10 )
- { fprintf(stderr, "Illegal value \"%s\" !\n", argv[i] );
- exit(1);
- }
- break;
-
- case 'd' : /* dots */
- c_filler = (argv[i][2]) ? argv[i][2] : ' ';
- break;
-
- case 'f' : /* include function-pointers */
- flag_funct_pointer = 1;
- break;
-
- case 'l' : /* Library symbols */
- if( argv[i][2] != '-' && argv[i][2] != 'm' )
- { fprintf(stderr, "Cannot recognize library-symbol-option \"%s\" !\n", argv[i] );
- fprintf(stderr, "Type \"brs_calltree -?\" for help !\n" );
- exit(1);
- }
- ignore_lib_symbols = ( argv[i][2] == '-' ) ? 1 : 0;
- mark_lib_symbols = ( argv[i][2] == 'm' ) ? 1 : 0;
-
- break;
-
- case 'c' : /* Characters */
- if( argv[i][2] != 'h' && argv[i][2] != 'v' &&
- argv[i][2] != 't' && argv[i][2] != 'c' &&
- argv[i][2] != 'b' )
- { fprintf(stderr, "Cannot recognize char-option \"%s\" !\n", argv[i] );
- fprintf(stderr, "Type \"brs_calltree -?\" for help !\n" );
- exit(1);
- }
- switch( argv[i][2] )
- { case 'h': /* horizontal line */
- c_hline = ( argv[i][3] ) ? argv[i][3] : ' ';
- break;
-
- case 'v': /* vertikal line */
- c_vline = ( argv[i][3] ) ? argv[i][3] : ' ';
- break;
-
- case 't': /* T-line */
- c_tline = ( argv[i][3] ) ? argv[i][3] : ' ';
- break;
- case 'c': /* corner */
- c_corner = ( argv[i][3] ) ? argv[i][3] : ' ';
- break;
- case 'b': /* begin */
- c_begin = ( argv[i][3] ) ? argv[i][3] : ' ';
- break;
- default:
- fprintf(stderr, "Unknown Option \"%s\" !\n", argv[i] );
- fprintf(stderr, "Type \"brs_calltree -?\" for help !\n" );
- exit(1);
- }
- break;
-
- case 'q' : /* quiet-flag: no Info to stderr */
- quiet_flag = 1;
- break;
-
- default:
- fprintf(stderr, "Unknown Option \"%s\" !\n", argv[i] );
- fprintf(stderr, "Type \"brs_calltree -?\" for help !\n" );
- exit(1);
- }
- }
- }
-
- /* create the strings needed to print the tree
- */
- create_output_strings();
-
- /* initialize hash-index-array used to hold the hash-indizes of the
- processed functions
- */
- hash_array = malloc(sizeof(long) * HASH_ARRAY_INIT_SIZE);
-
- if( !hash_array )
- { fprintf(stderr, "Error ! Cannot allocate %ld Bytes of Memory\n",
- sizeof( long ) * HASH_ARRAY_INIT_SIZE );
- exit( 1 );
- }
-
- hash_array_size = HASH_ARRAY_INIT_SIZE;
- hash_array_cnt = 0;
-
- /* initialize index-array for son-entries
- */
- son_hash_array = malloc(sizeof(struct son_e) * HASH_ARRAY_INIT_SIZE);
-
- if( !son_hash_array )
- { fprintf(stderr, "Error ! Cannot allocate %ld Bytes of Memory\n",
- sizeof( struct son_e ) * HASH_ARRAY_INIT_SIZE );
- exit( 1 );
- }
-
- son_hash_array_size = HASH_ARRAY_INIT_SIZE;
- son_hash_array_cnt = 0;
-
-
- /* get top-function-info
- */
- ret = brs_get_funct_pos( target_function, funct_filename,
- file, &line, &line_end, module);
-
- switch( ret )
- { case 0: break;
- case RET_TIMEOUT: fprintf(stderr, "No connection !\n");
- exit(1);
- case RET_ERROR: fprintf(stderr, "Error pos 0: %s %s \n", file, module);
- exit(1);
- default: fprintf(stderr, "Error pos 0: %d (%s %s) \n", ret,
- file, module);
- exit(1);
- }
-
- index = search_token( target_function, &h_data);
-
- if( index != TOKEN_NOT_FOUND &&
- h_data.flags & (FLAG_IGNORE | FLAG_TERMINATE) )
- { fprintf(stderr, "Target-function is exclude or terminate !\n");
- exit(1);
- }
-
- p_h_add = malloc( sizeof( t_hash_add ) );
- if( !p_h_add )
- { fprintf(stderr, "Not enough physical memory available !\n");
- exit(1);
- }
-
- /* init hash-add-struct of top-node
- */
- p_h_add->level = -1;
- p_h_add->cnt_sons = 0;
- p_h_add->total_cnt_n = 0;
- p_h_add->called = 0;
- p_h_add->father = TOKEN_NOT_FOUND;
-
- p_h_add->file = search_token( file, NULL);
- if( p_h_add->file == TOKEN_NOT_FOUND )
- { p_h_add->file = Add_ident_to_hash( file, 0,
- NULL, TYPE_FILE);
- }
- p_h_add->line = line;
-
- /* just used to calculate the length of the column "file,line"
- */
- if( flag_print_position == 2 )
- { /* just if definition position has to be printed
- */
- sprintf( module, file_line_format , file, line );
- p_h_add->pos.len = strlen(module);
- }
- else
- p_h_add->pos.len = 0;
-
- p_h_add->max_chars = calculate_max_chars( target_function, 0, p_h_add->pos.len);
-
- /* Add top-function to hash (every time, even if we do not
- have to print files)
- */
- index = Add_ident_to_hash(target_function, FLAG_IN_HASH |
- FLAG_TREE_TOP |
- FLAG_OWN_TREE,
- p_h_add, TYPE_FUNCTION);
-
- Add_to_Hash_Index_Array(index);
-
- if( flag_funct_pointer )
- { p_h_add = malloc( sizeof( t_hash_add ) );
- if( !p_h_add )
- { fprintf(stderr, "Not enough physical memory available !\n");
- exit(1);
- }
-
- /* init hash-add-struct of top-node
- */
- p_h_add->level = -1;
- p_h_add->cnt_sons = 0;
- p_h_add->total_cnt_n = 0;
- p_h_add->called = 0;
- p_h_add->father = TOKEN_NOT_FOUND;
-
- p_h_add->file = TOKEN_NOT_FOUND;
- p_h_add->line = 0;
- p_h_add->pos.len = 0;
-
- p_h_add->max_chars = calculate_max_chars( "?", 0, p_h_add->pos.len);
- index = Add_ident_to_hash( "?", FLAG_IN_HASH |
- FLAG_OWN_TREE,
- p_h_add, TYPE_FUNCTION);
-
- Add_to_Hash_Index_Array(index);
- }
-
- if( !quiet_flag )
- fprintf( stderr, "processing function ...\n");
-
- /* walk through the hash-index-array. initially, there is only the top
- node in it, but it (and therefore hash_array_cnt) will grow as long
- as there are unprocessed functions
- */
- for( i = 0; i < hash_array_cnt; i++ )
- { get_token ( &h_data, hash_array[i] );
-
- ret = 0;
-
- if( h_data.flags & FLAG_IGNORE )
- continue;
-
- if( h_data.flags & FLAG_TERMINATE )
- ret = RET_END;
-
- if( !quiet_flag )
- fprintf( stderr, "%ld/%ld: %s ", i, hash_array_cnt, h_data.ident );
-
- p_h_add = NULL;
- if( h_data.data )
- p_h_add = (t_hash_add *)h_data.data;
-
- /* copy the name of the function
- */
- if( strcmp( h_data.ident, "?" ) )
- strcpy( funct_in, h_data.ident );
- else
- strcpy( funct_in, "" );
-
- /* get filename of this function */
- if( p_h_add->file != TOKEN_NOT_FOUND )
- get_token ( &h_data_f, p_h_add->file );
- else
- strcpy( h_data_f.ident, "" );
-
- /* init local hash-indx-array to hold all the sons of this
- node
- */
- son_hash_array_cnt = 0;
-
- /* get all called function of this function
- */
- while( !ret )
- { ret = brs_get_funct_calls( funct_in, h_data_f.ident,
- !flag_full_tree,
- funct, file, &line, module, &static_flag);
-
- ignore_this_symbol = 0; /* default: add this symbol to son-array */
-
- if( !ret )
- { /* we found a son-node */
- /* check if function allready in hash-table
- */
- if( !quiet_flag )
- fprintf( stderr, "." );
-
- index_s = search_token(funct, &h_data_s);
- if( index_s == TOKEN_NOT_FOUND )
- { /* new function: allocate memory for additional data
- */
- p_h_add_s = malloc( sizeof( t_hash_add ) );
- if( !p_h_add_s )
- { fprintf(stderr, "Not enough physical memory available !\n");
- exit(1);
- }
- /* new entry: insert initial values
- */
- p_h_add_s->level = -1;
- p_h_add_s->called = 1;
- p_h_add_s->cnt_sons = 0;
- p_h_add_s->total_cnt_n = 0;
- p_h_add_s->father = TOKEN_NOT_FOUND;
-
- /* we have to get the definition-position of the function by using
- the get_funct_pos-call. the above function returns just the call-
- position.
- first try static function in file where this function was called
- */
- if( static_flag )
- ret2 = brs_get_funct_pos( funct, file, file2, &line2,
- &line_end, module);
- else
- ret2 = brs_get_funct_pos( funct, "", file2, &line2,
- &line_end, module);
-
- switch( ret2 )
- { case 0: case RET_END: /* store definition position */
- p_h_add_s->file = search_token( file2, NULL);
- if( p_h_add_s->file == TOKEN_NOT_FOUND )
- { p_h_add_s->file =
- Add_ident_to_hash( file2, 0,
- NULL, TYPE_FILE);
- }
- p_h_add_s->line = line2;
- break;
-
- case RET_TIMEOUT: fprintf(stderr, "No connection !\n");
- exit(1);
- case RET_ERROR: /* symbol could not be found withing the project
- */
- p_h_add_s->file = TOKEN_NOT_FOUND;
- p_h_add_s->line = 0;
- line2 = 0;
- file2[0] = 0;
-
- /* library symbol: do not add to son array */
- if( ignore_lib_symbols )
- ignore_this_symbol = 1;
-
- break;
- default: fprintf(stderr, "Error Pos2: %d (%s %s) \n", ret,
- file2, module);
- exit(1);
- }
-
-
- p_h_add_s->pos.file =
- search_token( file, NULL);
- if( p_h_add_s->pos.file == TOKEN_NOT_FOUND )
- { p_h_add_s->pos.file =
- Add_ident_to_hash(file, 0, NULL, TYPE_FILE);
- }
- p_h_add_s->pos.line = line;
- p_h_add_s->pos.next = NULL;
-
- /* just used to calculate the length of the column "file,line"
- */
- if( flag_print_position == 2 )
- { /* definition position */
- sprintf( module, file_line_format, file2, line2 );
- p_h_add_s->pos.len = strlen(module);
- }
- else if ( flag_print_position == 1 )
- { /* call position */
- sprintf( module, file_line_format, file, line );
- p_h_add_s->pos.len = strlen(module);
- }
- else
- p_h_add_s->pos.len = 0;
-
- index_s = Add_ident_to_hash(funct, FLAG_IN_HASH,
- p_h_add_s, TYPE_FUNCTION);
-
- Add_to_Hash_Index_Array(index_s);
-
- created_son.pos = &(p_h_add_s->pos);
- created_son.son = index_s;
-
- }
- else /* take pointer of allready allocated memory */
- { struct pos_e *tmp_pos, *last_pos;
-
- /* if we have to ignore this symbol: continue with
- next son
- */
- if( h_data_s.flags & FLAG_IGNORE )
- continue;
-
-
- if( !(h_data_s.flags & FLAG_IN_HASH) )
- { /* This ident is not stored in hash-array index.
- it has probaly entered by terminate or other
- files
- */
-
- Add_to_Hash_Index_Array(index_s);
-
- set_token_flag( index_s, h_data_s.flags | FLAG_IN_HASH );
- }
-
- p_h_add_s = (t_hash_add *)h_data_s.data;
-
- /* library symbole - maybe we have to ignore it */
- if( p_h_add_s->file == TOKEN_NOT_FOUND && ignore_lib_symbols )
- ignore_this_symbol = 1;
-
- else /* symbol has to be entered */
- { /* update entry:
- */
- p_h_add_s->called += 1;
-
- /* add new position to position list
- */
- last_pos = &(p_h_add_s->pos);
- tmp_pos = p_h_add_s->pos.next;
-
- while( tmp_pos ) /* get to end of the list */
- { last_pos = tmp_pos;
- tmp_pos = tmp_pos->next;
- }
-
- /* create a new position entry and add this one to the
- position-list of this call
- */
- tmp_pos = (struct pos_e *)malloc( sizeof(struct pos_e) );
-
- tmp_pos->file =
- search_token( file, NULL);
- if( tmp_pos->file == TOKEN_NOT_FOUND )
- { tmp_pos->file =
- Add_ident_to_hash( file, 0,
- NULL, TYPE_FILE);
- }
- tmp_pos->line = line;
- tmp_pos->next = NULL;
-
- /* just used to calculate the length of the column "file,line"
- */
- if( flag_print_position == 2 )
- { /* definition position -> allready calculated
- */
- /* sprintf( module, file_line_format,
- get_symbol( p_h_add_s->file ), p_h_add_s->line );
- */
- tmp_pos->len = last_pos->len;
- }
- else if ( flag_print_position == 1 )
- { /* call position */
- sprintf( module, file_line_format, file, line );
- tmp_pos->len = strlen(module);
- }
- else
- tmp_pos->len = 0;
-
- last_pos->next = tmp_pos;
-
- created_son.pos = tmp_pos;
- created_son.son = index_s;
- }
- }
-
- /* Store this son in the son_hash_array
- */
- if( !ignore_this_symbol )
- Add_to_Son_Array( created_son );
-
- } /* endif !ret */
- else
- { switch( ret )
- { case 0: case RET_END:
- break;
-
- case RET_TIMEOUT: fprintf(stderr, "No connection !\n");
- exit(1);
-
- case RET_ERROR: /* This function is not defined in the project:
- continue as it has no sons !
- */
- break;
-
- default: fprintf(stderr, "Error Pos 1: %d (%s %s) \n", ret,
- funct, file);
- exit(1);
- }
- }
-
- } /* endwhile */
-
- if( !quiet_flag )
- fprintf( stderr, "\n" );
-
-
-
- p_h_add->cnt_sons = son_hash_array_cnt;
-
- p_h_add->sons = (struct son_e *)malloc( sizeof(struct son_e) * son_hash_array_cnt);
- if( !(p_h_add->sons) )
- { fprintf(stderr, "Not enough physical memory available !\n");
- exit(1);
- }
-
- /* copy the indizes of the sons of this node to the father-node
- */
- memcpy( p_h_add->sons, son_hash_array,
- sizeof(struct son_e) * son_hash_array_cnt);
- } /* next i */
-
-
- if( !quiet_flag )
- fprintf( stderr, "calculating nodes for each subtree ...\n" );
-
- for( i = 0; i < hash_array_cnt; i++ )
- { get_token ( &h_data, hash_array[i] );
-
- if( h_data.flags & FLAG_IGNORE )
- continue;
-
- if( h_data.flags & FLAG_OWN_TREE )
- { /* for every own tree calculate numbers of nodes !
- maybe new trees has to be created
- */
- if( h_data.data )
- p_h_add = (t_hash_add *)h_data.data;
-
- get_total_nodes( hash_array[i], 0, &(p_h_add->pos) );
- if( !quiet_flag )
- fprintf( stderr, "subtree: %s\n", h_data.ident );
- }
- }
-
- if( !quiet_flag )
- fprintf( stderr, "Print subtrees ...\n" );
-
- for( i = 0; i < hash_array_cnt; i++ )
- { get_token ( &h_data, hash_array[i] );
-
- if( h_data.flags & FLAG_IGNORE )
- continue;
-
- if( h_data.flags & FLAG_OWN_TREE )
- { /* for every own tree calculate numbers of nodes !
- maybe new trees has to be created
- */
- if( h_data.data )
- p_h_add = (t_hash_add *)h_data.data;
-
- printf("\n\n\n");
-
- print_all_nodes( hash_array[i], 0, &(p_h_add->pos), 1);
- }
- }
-
- brs_disconnect_server();
-
- } /* end main */
-
-
-
- /* This function is recursivly called to process a calltree and returns
- the number of nodes in a subtree
- */
- static t_hash_data H_data;
- static short j;
-
- long get_total_nodes(long index, long level, struct pos_e *pos)
- { t_hash_add *p_h_add;
- long i;
- #ifdef CALLTREE_DEBUG
- char *ident;
- #endif
-
- get_token( &H_data, index);
- p_h_add = (t_hash_add *)H_data.data;
-
- #ifdef CALLTREE_DEBUG
- ident = H_data.ident;
- for( j = 0; j < level; j++ )
- fprintf(stderr, " " );
-
- fprintf(stderr, "%s (%d)", H_data.ident, level );
- fflush( stderr );
- #endif
-
- /* calculate the numer of characters used to print this function in this
- tree. Used to know the offset for the filenames in the output
- */
- p_h_add->max_chars = max( calculate_max_chars( H_data.ident, level, pos->len),
- p_h_add->max_chars);
-
- total_max_level = max( level, total_max_level );
-
- total_max_chars = max( total_max_chars, p_h_add->max_chars);
-
- if( p_h_add->level != -1 )
- { /* recursion: this node is allready called in this leave
- */
- #ifdef CALLTREE_DEBUG
- /* fprintf(stderr, " R\n" ); */
- #endif
- return( 1 );
- }
-
- if( p_h_add->cnt_sons == 0 )
- { /* terminal node - no sons */
- p_h_add->total_cnt_n = 0;
- p_h_add->level = -1;
-
- #ifdef CALLTREE_DEBUG
- fprintf(stderr, " T\n" );
- fflush( stderr );
- #endif
- return( 1 );
- }
-
- if( level && (H_data.flags & FLAG_OWN_TREE) )
- { /* this node will get an own tree: return if not top-node */
- p_h_add->total_cnt_n = 0;
- p_h_add->level = -1;
- #ifdef CALLTREE_DEBUG
- fprintf(stderr, " O\n" );
- fflush( stderr );
- #endif
- return( 1 );
- }
-
- p_h_add->level = level;
- p_h_add->total_cnt_n = 0;
-
- #ifdef CALLTREE_DEBUG
- fprintf(stderr, "\n" );
- fflush( stderr );
- #endif
-
- for( i = 0; i < p_h_add->cnt_sons; i++ )
- {
- #ifdef CALLTREE_DEBUG
- fprintf(stderr, "%s [%ld:%ld/%ld] ", ident, level, i,
- p_h_add->cnt_sons );
- fflush( stderr );
- #endif
-
- p_h_add->total_cnt_n +=
- get_total_nodes( p_h_add->sons[i].son, level + 1,
- p_h_add->sons[i].pos );
- }
- #ifdef CALLTREE_DEBUG
- fprintf(stderr, "\n" );
- fflush( stderr );
- #endif
-
- /* reset this node */
- p_h_add->level = -1;
-
- /* find out, if we have to use an own tree for this node
- */
- if( trshold_called )
- { if( p_h_add->called >= trshold_called &&
- p_h_add->total_cnt_n >= trshold_sons )
- { /* this function should be printed in an own tree
- */
- set_token_flag( index, get_token_flag(index) | FLAG_OWN_TREE );
- }
- }
-
- return( p_h_add->total_cnt_n );
- }
-
-
- /* This function is recursivly called to process a calltree and prints
- a line for every called function
- */
- void print_all_nodes(long index, long level, struct pos_e *pos, char last)
- { t_hash_add *p_h_add;
- long i;
-
- get_token( &H_data, index);
- p_h_add = (t_hash_add *)H_data.data;
-
-
- if( p_h_add->level != -1 )
- { /* recursion: this node is allready called in this leave
- */
- print_line( level, H_data.ident, p_h_add, pos, "... (R) ", last);
- return;
- }
-
- if( level && (H_data.flags & FLAG_OWN_TREE) )
- { /* This node will (or has been allready) printed in an own tree !
- Do not process further
- */
- p_h_add->level = -1;
-
- print_line( level, H_data.ident, p_h_add, pos, "... (T) ", last);
- return;
- }
-
- if( p_h_add->cnt_sons == 0 )
- { /* terminal node - no sons - might also be a library symbol */
- p_h_add->level = -1;
-
- if( p_h_add->file != TOKEN_NOT_FOUND || !mark_lib_symbols )
- print_line( level, H_data.ident, p_h_add, pos, " ", last);
- else
- print_line( level, H_data.ident, p_h_add, pos, " (L) ", last);
- return;
- }
-
- p_h_add->level = level;
-
- print_line( level, H_data.ident, p_h_add, pos, " ", last);
-
- for( i = 0; i < p_h_add->cnt_sons; i++ )
- { print_all_nodes( p_h_add->sons[i].son, level + 1,
- p_h_add->sons[i].pos,
- (i == (p_h_add->cnt_sons)-1) ? 1 : 0 );
- }
-
- /* reset this node */
- p_h_add->level = -1;
-
- return;
- }
-
-
-
- void print_line( long level, char *ident, t_hash_add *add, struct pos_e *pos,
- char *suffix, char last_flag)
- { static char *last_level_flags = NULL;
- long i;
-
- output_line[0] = 0;
-
- if( !last_level_flags )
- { last_level_flags = malloc( total_max_level + 2 );
- if( !last_level_flags )
- { fprintf(stderr, "Not enough physical memory available !\n");
- exit(1);
- }
- }
-
- last_level_flags[level] = last_flag;
-
- /* Do the indenting
- */
- for( i = 1; i < level; i++ )
- { if( last_level_flags[i] )
- { /* last flag set in this level: print an empty column
- */
- sprintf( output_line + strlen(output_line), "%s" , blank_pre );
- }
- else
- { /* last flag not set in this level: print like "| "
- */
- sprintf( output_line + strlen(output_line), "%s" , noblank_pre );
- }
- }
-
- if( level ) /* only indenting, if we are not at toplevel */
- { if( last_flag )
- sprintf( output_line + strlen(output_line), "%s", last_string );
- else
- sprintf( output_line + strlen(output_line),"%s", mid_string );
- }
-
- /* Output the symbol
- */
- if( strlen(output_line) + strlen(ident) + strlen( suffix) > line_length )
- { /* does not fit in this line ! create a new one and indent data
- */
- printf( "%s\n", output_line );
- output_line[0] = 0;
- for( i = line_length; i > strlen(ident) + strlen( suffix) + pos->len + 8; i--)
- { sprintf( output_line + strlen(output_line)," " );
- }
- }
- sprintf( output_line + strlen(output_line), "%s%s", ident, suffix );
-
- /* print no position or print called-position and main function:
-
- do nothing and return
- */
- if( !flag_print_position || (flag_print_position == 1 && level == 0) )
- { printf( "%s\n", output_line );
- return;
- }
-
- if( flag_print_position == 2 && add->file == TOKEN_NOT_FOUND )
- { /* definition position of function unknown
- */
- printf( "%s\n", output_line );
- return;
- }
-
- if( strlen(output_line) + pos->len > line_length )
- { /* file/line does not fit in this line ! create a new one and indent data
- */
- printf( "%s\n", output_line );
- output_line[0] = 0;
- for( i = line_length; i > pos->len + 8; i--)
- { sprintf( output_line + strlen(output_line)," " );
- }
- }
-
- /* print dots */
- for( i = strlen(output_line); i < line_length - pos->len; i++ )
- { sprintf( output_line + strlen(output_line), "%s", filler_string);
- }
-
-
- if( flag_print_position == 1 )
- { /* Print called position provided by the pos-arg
- */
- sprintf( output_line + strlen(output_line), file_line_format,
- get_symbol(pos->file), pos->line);
- }
- else if( flag_print_position == 2 )
- { /* Print definition position in add
- */
- sprintf( output_line + strlen(output_line), file_line_format,
- get_symbol(add->file), add->line);
- }
-
- printf( "%s\n", output_line );
- }
-